#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>

// initializes an array
void initialize(int * a, int size, int value)
{
	while ( size)
		a[--size] = value;
}

int main(int argc, char * argv[])
{
	printf("Go\n");
	
	// inits MPI
	int mpi_error = MPI_Init(&argc, &argv);
	{
		int process_count = 0;
		int rank = 0;
		
		// retrieves rank and count of processes
		mpi_error = MPI_Comm_size(MPI_COMM_WORLD, &process_count);
		mpi_error = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
		
		// allocates array
		int * vec = NULL;
		int size = process_count;
		
		if ( rank == 0 )
		{
			printf("Program starts (%d/%d)\n", rank, process_count);
			
			vec = (int*)(malloc(size * sizeof(int)));
			initialize(vec, size, 0);
			for(int i = 0; i < size; ++i)
			{
				printf(" %d: %d", i, vec[i]);
			}
			printf("\n");
		}
		
		int local = 0;
		
		MPI_Scatter(vec, 1, MPI_INT, &local, 1, MPI_INT, 0, MPI_COMM_WORLD);
		
		local = rank + 1;
		
		MPI_Gather(&local, 1, MPI_INT, vec, 1, MPI_INT, 0, MPI_COMM_WORLD);
		
		if ( rank == 0 )
		{
			int success = 1;
			for(int i = 0; i < size; ++i)
			{
				printf(" %d: %d", i, vec[i]);
				if ( vec[i] != i+1 )
					success = 0;
			}
			printf("\nFinished with %s\n\n", ((success != 0 )? "success" : "fails"));
		}
		
		// deallocates array
		if ( vec )
			free(vec);
	}
	mpi_error = MPI_Finalize(); // destructs MPI environment
	
	return mpi_error;
}
